package com.wiz.web.service.impl;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.google.gson.reflect.TypeToken;
import com.wiz.common.util.DateUtil;
import com.wiz.vo.criteria.PayCriteria;
import com.wiz.vo.to.PayOrderTO;
import com.wiz.vo.to.xunlian.XlPayReqData;
import com.wiz.vo.to.xunlian.XlPayResData;
import com.wiz.vo.type.PayMethodType;
import com.wiz.web.dao.mapper.XlPayMapper;
import com.wiz.web.manager.HttpManager;
import com.wiz.web.manager.fatory.XlDataFactory;
import com.wiz.web.service.XlService;

@SuppressWarnings("all")
@Service("xlService")
public class XlServiceImpl extends BasicServiceImpl implements XlService {
	private transient final Logger log = LoggerFactory.getLogger(getClass());

	@Resource
	private XlDataFactory xlDataFactory;
	@Resource
	private XlPayMapper xlPayMapper;
	@Resource
	private HttpManager httpManager;
	
	@Override
	public String xlBarPay(String msg, String hqId, String stationId,String xlMerchantId, int channelType, 
			String terminalId, String signKey) throws Exception{
		log.info("stationId="+stationId+" using aliBarPay in XL,params="+msg);
		PayCriteria criteria = gson.fromJson(msg, new TypeToken<PayCriteria>(){}.getType());
		criteria.setHqId(hqId);
		criteria.setStationId(stationId);
		criteria.setFuellingOrderId(criteria.getOutTradeNo());
		criteria.setOutTradeNo(createXlOutTradeNo(stationId));
		criteria.setSubMchId(xlMerchantId);
		criteria.setSignKey(signKey);
		criteria.setTerminalId(terminalId);
		XlPayReqData reqData = (XlPayReqData) xlDataFactory.getDataByType(criteria,PayMethodType.BAR_PAY.getId(),channelType);
		String response = httpManager.sendXlPost(XL_IP, gson.toJson(reqData));
		XlPayResData resData = gson.fromJson(response, new TypeToken<XlPayResData>(){}.getType());
		if(resData.getRespcd().equals(XL_RETURN_CODE_SUCCESS)){//支付成功
			criteria.setTransactionId(resData.getChannelOrderNum());
			criteria.setResult(response);
			criteria.setPayTime(DateUtil.formatDateTime(System.currentTimeMillis()));
			criteria.setStatus(1);
			xlPayMapper.insertXlPayOrder(criteria);
			PayOrderTO order = new PayOrderTO();
			order.setFuellingOrderId(criteria.getFuellingOrderId());
			order.setPayOrderId(criteria.getOutTradeNo());
			order.setRefOrderId(resData.getChannelOrderNum());
			return returnResult(CODE_OK, STRING_OK, order);
		}else if(resData.getRespcd().equals(XL_RETURN_CODE_PROCCESS)){
			int each = 0;
			XlPayResData responseData = null;
			Thread.currentThread().sleep(2000);
			while(each<4){//30秒后
				criteria.setTransactionId(criteria.getOutTradeNo());
				responseData = queryXlOrder(criteria,channelType);
				if(resData.getRespcd().equals(XL_RETURN_CODE_SUCCESS)){
					criteria.setResult(response);
					criteria.setPayTime(DateUtil.formatDateTime(System.currentTimeMillis()));
					criteria.setStatus(1);
					xlPayMapper.insertXlPayOrder(criteria);
					PayOrderTO order = new PayOrderTO();
					order.setFuellingOrderId(criteria.getFuellingOrderId());
					order.setPayOrderId(criteria.getOutTradeNo());
					order.setRefOrderId(resData.getChannelOrderNum());
					return returnResult(CODE_OK, STRING_OK, order);
				}
				if(each==3){
					log.info(criteria.getOutTradeNo()+" will Reverse order");
					return getResponseFromReverse(criteria,channelType);
				}
				each++;
				Thread.currentThread().sleep(10000);
			}
		}else{
			return returnResult(CODE_ALI_ERROR, resData.getErrorDetail(), null);
		}
		log.warn("stationId="+stationId+"pay fail,response=" + response +",reverseXlOrder will begin after 16s");
		Thread.currentThread().sleep(16000);
		criteria.setTransactionId(criteria.getOutTradeNo());
		return getResponseFromReverse(criteria,channelType);
	}

	/**
	 * 查询讯联订单
	 * @param criteria
	 * @return
	 */
	private XlPayResData queryXlOrder(PayCriteria criteria, int channelType){
		XlPayReqData payData = (XlPayReqData) xlDataFactory.getDataByType(criteria,PayMethodType.QUERY.getId(),channelType);
		return gson.fromJson(httpManager.sendXlPost(XL_IP, gson.toJson(payData)), new TypeToken<XlPayResData>(){}.getType());
	}
	
	/**
	 * 撤销讯联订单
	 * @param criteria
	 * @return
	 */
	private XlPayResData reverseXlOrder(PayCriteria criteria, int channelType){
		criteria.setOutRefundNo(createXlOutTradeNo(criteria.getStationId()));
		XlPayReqData payData = (XlPayReqData) xlDataFactory.getDataByType(criteria,PayMethodType.REVERSE.getId(),channelType);
		return gson.fromJson(httpManager.sendXlPost(XL_IP, gson.toJson(payData)), new TypeToken<XlPayResData>(){}.getType());
	}
	
	/**
	 * 取消讯联订单，成功订单会发生退款
	 * @param criteria
	 * @param channelType
	 * @return
	 */
	private XlPayResData refundXlOrder(PayCriteria criteria, int channelType){
		criteria.setOutRefundNo(createXlOutTradeNo(criteria.getStationId()));
		XlPayReqData payData = (XlPayReqData) xlDataFactory.getDataByType(criteria,PayMethodType.REFUND.getId(),channelType);
		return gson.fromJson(httpManager.sendXlPost(XL_IP, gson.toJson(payData)), new TypeToken<XlPayResData>(){}.getType());
	}
	
	/**
	 * 解析撤销返回结果
	 * @param criteria
	 * @return
	 */
	private String getResponseFromReverse(PayCriteria criteria, int channelType){
		XlPayResData responseDataReverse = refundXlOrder(criteria,channelType);
		log.info("XL responseDataReverse-------------------------");
		if(responseDataReverse.getRespcd().equals(XL_RETURN_CODE_SUCCESS)){//撤销成功
			return RESPONSE_WX_PAY_FAIL;
		}else {//撤销失败后
			responseDataReverse = queryXlOrder(criteria,channelType);
			if(responseDataReverse.getRespcd().equals(XL_RETURN_CODE_SUCCESS)){
				criteria.setResult(gson.toJson(responseDataReverse));
				criteria.setPayTime(DateUtil.formatDateTime(System.currentTimeMillis()));
				criteria.setStatus(1);
				xlPayMapper.insertXlPayOrder(criteria);
				PayOrderTO order = new PayOrderTO();
				order.setFuellingOrderId(criteria.getFuellingOrderId());
				order.setPayOrderId(criteria.getOutTradeNo());
				order.setRefOrderId(responseDataReverse.getChannelOrderNum());
				return returnResult(CODE_OK, STRING_OK, order);
			}else{
				log.warn("Reverse xlOrder fail, result="+responseDataReverse.toString());
				return RESPONSE_WX_PAY_FAIL;
			}
		}
	}
	
	
	/**
	 * 支付订单号
	 * @param stationId
	 * @return
	 */
	private String createXlOutTradeNo(String stationId){
		return "XL"+stationId+System.currentTimeMillis()+getRandom(5);
	}

	/**
	 * 备份支付前的数据以便查询操作
	 * @param criteria
	 * @return
	 */
	private int backupPayData(PayCriteria criteria){
		criteria.setStatus(0);
		criteria.setBody("讯联消费");
		return xlPayMapper.insertXlPayOrder(criteria);
	}
	
	/**
	 * 更新数据
	 * @param criteria
	 * @return
	 */
	private int updatePayData(PayCriteria criteria, XlPayResData resData,String response){
		criteria.setResult(response);
		criteria.setStatus(1);
		return xlPayMapper.updateXlPayOrder(criteria);
	}
	
	
	/**
	 * 验签
	 * @param resData
	 * @return
	 */
	public boolean checkXlSignture(XlPayResData resData, String signKey){
		String sign = resData.getSign();
		resData.setSign(null);
		String checkSign =resData.toSign(signKey);
		if(checkSign.equals(sign)){
			return true;
		}
		return false;
	}

	@Override
	public String xlRefund(String msg, String hqId, String stationId,
			String xlMerchantId, int channelType, String terminalId, String signKey) throws Exception {
		PayCriteria criteria = gson.fromJson(msg, new TypeToken<PayCriteria>(){}.getType());
		criteria.setHqId(hqId);
		criteria.setStationId(stationId);
//		criteria.setFuellingOrderId(criteria.getOutTradeNo());
		criteria.setOutTradeNo(createXlOutTradeNo(stationId));
		criteria.setSubMchId(xlMerchantId);
		criteria.setTerminalId(terminalId);
		criteria.setSignKey(signKey);
		XlPayResData responseData = refundXlOrder(criteria,channelType);
		return RESPONSE_CODE_OK;
	}
	

}
